package com.cmc.cloud.cmclink.doc.api.document;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cmc.cloud.cmclink.doc.api.document.emums.SoDataSourceEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.TransmodeEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.ValidStatusEnum;
import com.cmc.cloud.cmclink.doc.api.document.rep.*;
import com.cmc.cloud.cmclink.doc.api.document.req.CheckSoCombineSiVO;
import com.cmc.cloud.cmclink.doc.api.document.req.so.*;
import com.cmc.cloud.cmclink.doc.convert.*;
import com.cmc.cloud.cmclink.doc.entity.BlnoDO;
import com.cmc.cloud.cmclink.doc.entity.SoDO;
import com.cmc.cloud.cmclink.doc.entity.SoVslvoyDO;
import com.cmc.cloud.cmclink.doc.mapper.*;
import com.cmc.cloud.cmclink.doc.service.si.BlnoService;
import com.cmc.cloud.cmclink.doc.service.so.SoSplitCombineService;
import com.cmc.cloud.cmclink.doc.vo.blnovo.BlnoForecastReqVO;
import com.cmc.cloud.cmclink.doc.vo.blnovo.BlnoInfoVO;
import com.cmc.cloud.cmclink.doc.vo.blnovo.BlnoMultipleSoCreateVO;
import com.cmc.cloud.cmclink.doc.vo.blnovo.BlnoMultipleSoVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.socargovo.SoCargoSumVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.soforecastvo.SoForecastSumVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.sosplitcombinedetailvo.SoCombineCreateReqVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.sosplitcombinedetailvo.SoSplitCombineAllRespVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.sosplitcombinedetailvo.SoSplitCombinePageReqVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.sosplitcombinedetailvo.SoSplitCreateReqVO;
import com.cmes.framework.common.pojo.CommonResult;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cmes.framework.security.core.util.SecurityFrameworkUtils;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订舱拆分合并api实现类
 *
 * @author wzb
 * @date 2025/08/29
 */
@RestController
@Valid
public class SoSplitCombineApiImpl implements SoSplitCombineApi  {
    @Resource
    private SoSplitCombineService soSplitCombineService;

    @Resource
    private SoMapper soMapper;

    @Resource
    private SoCargoMapper soCargoMapper;

    @Resource
    private SoForecastMapper soForecastMapper;

    @Resource
    private SoVslvoyMapper soVslvoyMapper;

    @Resource
    private BlnoMapper blnoMapper;
    @Resource
    private BlnoService blnoService;

    @Override
    public CommonResult<PageResult<SoRespDto>> querySoInfo(SoPageReqDto soPageReqDto) {
        IPage<SoDO> page = Page.of(soPageReqDto.getPageNo(), soPageReqDto.getPageSize());
        IPage<SoDO> pageResult = soMapper.rpcQuerySoInfo(page, soPageReqDto);
        SoRespDto mainSoRespDto = null;
        // 获得主单信息
        Optional<SoDO> optionalResult = pageResult.getRecords().stream().filter(soDO -> Objects.equals(soDO.getId(), soPageReqDto.getId())).findFirst();
        if(optionalResult.isPresent()){
            mainSoRespDto = SoConvert.INSTANCE.convertSoDO(optionalResult.get());
        }
        List<SoDO> filteredSoDoList = pageResult.getRecords().stream()
                .filter(soDO -> hasSiByBookingNo(soDO.getBookingNo()))
                .collect(Collectors.toList());
        List<SoRespDto> soRespDtoList = SoConvert.INSTANCE.convertSoRespDto(filteredSoDoList);
        // 没有一个符合条件也要将主单返回
        if (CollectionUtils.isEmpty(soRespDtoList)) {
            if(mainSoRespDto != null){
                soRespDtoList.add(mainSoRespDto);
            }else{
                return CommonResult.success(new PageResult<>());
            }
        }else{
            boolean flag = soRespDtoList.stream().map(SoRespDto::getId).anyMatch(e -> Objects.equals(e, soPageReqDto.getId()));
            if(!flag){
                // 主单不存在(已经生成提单)那其余可合并订舱数据不返回
                soRespDtoList.clear();
                // 只返回主单数据
                soRespDtoList.add(mainSoRespDto);
            }
        }
        List<Long> soIds = soRespDtoList.stream().map(SoRespDto::getId).collect(Collectors.toList());
        //查询货物信息
        Map<Long, SoCargoSumVO> cargoSumMap = soCargoMapper.selectSumBySoIds(soIds).stream().collect(Collectors.toMap(SoCargoSumVO::getSoId, e -> e));
        //查询预配箱信息
        Map<Long, SoForecastSumVO> forecastSumMap = soForecastMapper.selectSumBySoIds(soIds).stream().collect(Collectors.toMap(SoForecastSumVO::getSoId, e -> e));
        //查询航线信息
        Map<Long, SoVslvoyDO> soVslvoyDoMap = soVslvoyMapper.seleceFirstLinerBySoIds(soIds, TransmodeEnum.LINER.getValue()).stream().collect(Collectors.toMap(SoVslvoyDO::getSoId, e -> e));
        //集中处理返回的信息
        soRespDtoList.forEach(e -> {
            SoCargoSumVO cargoSum = cargoSumMap.get(e.getId());
            if (cargoSum != null) {
                e.setCargoTypeSum(cargoSum.getCargoTypeSum());
                e.setSubCargoTypeSum(cargoSum.getSubCargoTypeSum());
                e.setGrossWeightSum(cargoSum.getGrossWeightSum());
            }
            SoForecastSumVO forecastSum = forecastSumMap.get(e.getId());
            if (forecastSum != null) {
                e.setForecastDesc(forecastSum.getForecastDesc());
            }
            SoVslvoyDO soVslvoyDo = soVslvoyDoMap.get(e.getId());
            if (soVslvoyDo != null) {
                e.setLaneCodeEx(soVslvoyDo.getLaneCodeEx());
            }
        });
        PageResult<SoRespDto> soDoPageResult = new PageResult<>(soRespDtoList, Long.valueOf(filteredSoDoList.size()));
        return CommonResult.success(soDoPageResult);
    }

    public boolean hasSiByBookingNo(String bookingNo) {
        return blnoMapper.selectCount(BlnoDO::getBookingNo, bookingNo) == 0;
    }

    @Override
    public CommonResult<SoDetailRespDto> getSoDetailForSplitAndCombine(Long soId) {
        return CommonResult.success(SoDetailConvert.INSTANCE.convert(soSplitCombineService.getSoDetailForSplitAndCombine(soId)));
    }

    @Override
    public CommonResult<List<SoDetailRespDto>> getSoDetailListForSplitAndCombine(List<Long> soIds) {
        return CommonResult.success(SoDetailConvert.INSTANCE.convert(soSplitCombineService.getSoDetailListForSplitAndCombine(soIds)));
    }

    @Override
    public CommonResult<Void> createSoSplit(SoSplitCreateReqDto createReqDto) {
        SoSplitCreateReqVO createReqVO= SoSplitCreateConvert.INSTANCE.convert(createReqDto);
        soSplitCombineService.createSoSplit(createReqVO, String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        return CommonResult.success();
    }

    @Override
    public CommonResult<Void> createSoCombine(SoCombineCreateReqDto updateReqDto) {
        SoCombineCreateReqVO updateReqVO= SoCombineCreateConvert.INSTANCE.convert(updateReqDto);
        soSplitCombineService.createSoCombine(updateReqVO, String.valueOf(SecurityFrameworkUtils.getLoginUserId()));
        return CommonResult.success();
    }

    @Override
    public CommonResult<SoSplitCombineAllRespDto> getSoSplitCombineDetail(Long splitCombineId) {
        SoSplitCombineAllRespVO soSplitCombine = soSplitCombineService.getSoSplitCombine(splitCombineId);
        SoSplitCombineAllRespDto soSplitCombineAllRespDto = SoSplitCombineConvert.INSTANCE.convert(soSplitCombine);
        return CommonResult.success(soSplitCombineAllRespDto);
    }

    @Override
    public CommonResult<PageResult<SoSplitCombinePageRespDto>> getSoSplitCombinePage(SoSplitCombinePageReqDto pageDto) {
        SoSplitCombinePageReqVO soSplitCombinePage=SoSplitCombineConvert.INSTANCE.convert(pageDto);
        return CommonResult.success(SoSplitCombineConvert.INSTANCE.convert(soSplitCombineService.getSoSplitCombinePage(soSplitCombinePage)));
    }

    @Override
    public CommonResult<List<SoBookingNoVO>> getCombineBookingNoList(String bookingNo,String csmCode) {
        return CommonResult.success(soSplitCombineService.getCombineBookingNoList(bookingNo,csmCode));
    }

    @Override
    public CommonResult<List<CheckSoCombineSiVO>> checkSoCombineSi(BlnoForecastReqDto dto){
        return CommonResult.success(soSplitCombineService.checkSoCombineSi(dto));
    }

    @Override
    public CommonResult<Long> createSoCombineSi(BlnoMultipleSoCreateDto dto) {
        BlnoMultipleSoCreateVO createDto = new BlnoMultipleSoCreateVO();
        createDto.setBlnoMultipleSoVO(BeanUtil.copyProperties(dto.getBlnoMultipleSoVO(), BlnoMultipleSoVO.class));
        createDto.setBlnoInfoVO(BeanUtil.copyProperties(dto, BlnoInfoVO.class));
        return CommonResult.success(blnoService.createSoCombineSi(createDto));
    }

    @Override
    public CommonResult<Long> commitSoCombineSi(BlnoMultipleSoCreateDto dto) {
        BlnoMultipleSoCreateVO createDto = new BlnoMultipleSoCreateVO();
        createDto.setBlnoMultipleSoVO(BeanUtil.copyProperties(dto.getBlnoMultipleSoVO(), BlnoMultipleSoVO.class));
        createDto.setBlnoInfoVO(BeanUtil.copyProperties(dto, BlnoInfoVO.class));
        return CommonResult.success(blnoService.commitSoCombineSi(createDto));
    }

    @Override
    public CommonResult<List<SoForecastRespVO>> getForecastInfo(BlnoForecastReqDto dto) {
        return CommonResult.success(blnoService.getForecastInfo(BeanUtil.copyProperties(dto, BlnoForecastReqVO.class)));
    }
}
